package com.jintian.smart.kernel.message.service;

import com.google.common.collect.Maps;
import com.jintian.smart.base.api.message.constant.NoticeVisibleRangeDataTypeEnum;
import com.jintian.smart.base.api.message.entity.NoticeEntity;
import com.jintian.smart.base.api.message.form.NoticeAddForm;
import com.jintian.smart.base.api.message.form.NoticeQueryForm;
import com.jintian.smart.base.api.message.form.NoticeUpdateForm;
import com.jintian.smart.base.api.message.form.NoticeVisibleRangeForm;
import com.jintian.smart.base.api.message.vo.NoticeTypeVO;
import com.jintian.smart.base.api.message.vo.NoticeUpdateFormVO;
import com.jintian.smart.base.api.message.vo.NoticeVO;
import com.jintian.smart.base.api.message.vo.NoticeVisibleRangeVO;
import com.jintian.smart.base.api.security.constant.DataTracerTypeEnum;
import com.jintian.smart.base.api.security.provider.IDataTracerProvider;
import com.jintian.smart.base.api.system.entity.EmployeeEntity;
import com.jintian.smart.base.api.system.provider.IDepartmentProvider;
import com.jintian.smart.base.api.system.provider.IEmployeeProvider;
import com.jintian.smart.base.api.system.view.DepartmentVO;
import com.jintian.smart.base.api.system.entity.DepartmentEntity;
import com.jintian.smart.kernel.common.util.SmartBeanUtil;
import com.jintian.smart.kernel.core.constant.StringConst;
import com.jintian.smart.kernel.core.domain.ResponseDTO;
import com.jintian.smart.kernel.message.mapper.NoticeMapper;
import com.jintian.smart.kernel.orm.impl.AbstractEntityServiceImpl;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.beetl.sql.core.page.PageResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 通知、公告 后台管理业务
 */
@Service
public class NoticeService extends AbstractEntityServiceImpl<NoticeMapper, NoticeEntity> {
    @Resource
    private NoticeTypeService noticeTypeService;

    @DubboReference
    private IEmployeeProvider employeeProvider;

    @DubboReference
    private IDepartmentProvider departmentProvider;

    @DubboReference
    private IDataTracerProvider dataTracerProvider;

    /**
     * 查询 通知、公告
     */
    public PageResult<NoticeVO> query(NoticeQueryForm queryForm) {
        PageResult<NoticeVO> page = this.entityMapper.query(queryForm);
        LocalDateTime now = LocalDateTime.now();
        page.getList().forEach(e -> e.setPublishFlag(e.getPublishTime().isBefore(now) ? 1 : 0));
        return page;
    }

    /**
     * 添加
     */
    public ResponseDTO<String> add(NoticeAddForm addForm) {
        // 校验并获取可见范围
        ResponseDTO<String> validate = this.checkAndBuildVisibleRange(addForm);
        if (!validate.getOk()) {
            return ResponseDTO.error(validate);
        }

        // build 资讯
        NoticeEntity noticeEntity = SmartBeanUtil.copy(addForm, NoticeEntity.class);
        // 发布时间：不是定时发布时 默认为 当前
        if (addForm.getScheduledPublishFlag() == 1) {
            noticeEntity.setPublishTime(LocalDateTime.now());
        }
        // 保存数据
        this.save(noticeEntity, addForm.getVisibleRangeList());
        return ResponseDTO.ok();
    }

    /**
     * 校验并返回可见范围
     */
    private ResponseDTO<String> checkAndBuildVisibleRange(NoticeAddForm form) {
        // 校验资讯分类
        NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(form.getNoticeTypeId());
        if (noticeType == null) {
            return ResponseDTO.userErrorParam("分类不存在");
        }

        if (form.getAllVisibleFlag() == 1) {
            return ResponseDTO.ok();
        }

        /*
         * 校验可见范围
         * 非全部可见时 校验选择的员工|部门
         */
        List<NoticeVisibleRangeForm> visibleRangeUpdateList = form.getVisibleRangeList();
        if (CollectionUtils.isEmpty(visibleRangeUpdateList)) {
            return ResponseDTO.userErrorParam("未设置可见范围");
        }

        // 校验可见范围-> 员工
        List<Long> employeeIdList = visibleRangeUpdateList.stream()
                .filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()))
                .map(NoticeVisibleRangeForm::getDataId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(employeeIdList)) {
            employeeIdList = employeeIdList.stream().distinct().collect(Collectors.toList());
            List<Long> dbEmployeeIdList = employeeProvider.listByIds(employeeIdList).stream().map(EmployeeEntity::getEmployeeId).collect(Collectors.toList());
            Collection<Long> subtract = CollectionUtils.subtract(employeeIdList, dbEmployeeIdList);
            if (!subtract.isEmpty()) {
                return ResponseDTO.userErrorParam("员工id不存在：" + subtract);
            }
        }

        // 校验可见范围-> 部门
        List<Long> deptIdList = visibleRangeUpdateList.stream()
                .filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType()))
                .map(NoticeVisibleRangeForm::getDataId)
                .distinct().collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(deptIdList)) {
            deptIdList = deptIdList.stream().distinct().collect(Collectors.toList());
            List<Long> dbDeptIdList = departmentProvider.listByIds(deptIdList).stream().map(DepartmentEntity::getDepartmentId).collect(Collectors.toList());
            Collection<Long> subtract = CollectionUtils.subtract(deptIdList, dbDeptIdList);
            if (!subtract.isEmpty()) {
                return ResponseDTO.userErrorParam("部门id不存在：" + subtract);
            }
        }
        return ResponseDTO.ok();
    }


    /**
     * 更新
     */
    public ResponseDTO<String> update(NoticeUpdateForm updateForm) {
        NoticeEntity oldNoticeEntity = this.getEntityMapper().single(updateForm.getNoticeId());
        if (oldNoticeEntity == null) {
            return ResponseDTO.userErrorParam("通知不存在");
        }

        // 校验并获取可见范围
        ResponseDTO<String> res = this.checkAndBuildVisibleRange(updateForm);
        if (!res.getOk()) {
            return ResponseDTO.error(res);
        }

        // 更新
        NoticeEntity noticeEntity = SmartBeanUtil.copy(updateForm, NoticeEntity.class);
        this.update(oldNoticeEntity, noticeEntity, updateForm.getVisibleRangeList());
        return ResponseDTO.ok();
    }


    /**
     * 删除
     */
    public ResponseDTO<String> delete(Long noticeId) {
        NoticeEntity noticeEntity = this.getById(noticeId);
        if (null == noticeEntity || noticeEntity.getDeletedFlag() == 1) {
            return ResponseDTO.userErrorParam("通知公告不存在");
        }
        // 更新删除状态
        this.getEntityMapper().updateDeletedFlag(noticeId);
        dataTracerProvider.delete(noticeId, DataTracerTypeEnum.OA_NOTICE);
        return ResponseDTO.ok();
    }

    /**
     * 获取更新表单用的详情
     */
    public NoticeUpdateFormVO getUpdateFormVO(Long noticeId) {
        NoticeEntity noticeEntity = this.getById(noticeId);
        if (null == noticeEntity) {
            return null;
        }

        NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class);
        NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId());
        updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName());
        updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now()) ? 1 : 0);

        if (updateFormVO.getAllVisibleFlag() == 0) {
            List<NoticeVisibleRangeVO> noticeVisibleRangeList = this.getEntityMapper().queryVisibleRange(noticeId);
            List<Long> employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType()))
                    .map(NoticeVisibleRangeVO::getDataId)
                    .collect(Collectors.toList());

            Map<Long, EmployeeEntity> employeeMap = null;
            if (CollectionUtils.isNotEmpty(employeeIdList)) {
                employeeMap = employeeProvider.listByIds(employeeIdList).stream().collect(Collectors.toMap(EmployeeEntity::getEmployeeId, Function.identity()));
            } else {
                employeeMap = Maps.newHashMap();
            }
            for (NoticeVisibleRangeVO noticeVisibleRange : noticeVisibleRangeList) {
                if (noticeVisibleRange.getDataType().equals(NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue())) {
                    EmployeeEntity employeeEntity = employeeMap.get(noticeVisibleRange.getDataId());
                    noticeVisibleRange.setDataName(employeeEntity == null ? StringConst.EMPTY : employeeEntity.getActualName());
                } else {
                    DepartmentVO departmentVO = departmentProvider.getDepartmentById(noticeVisibleRange.getDataId());
                    noticeVisibleRange.setDataName(departmentVO == null ? StringConst.EMPTY : departmentVO.getDepartmentName());
                }
            }
            updateFormVO.setVisibleRangeList(noticeVisibleRangeList);
        }
        return updateFormVO;
    }

    /**
     * 保存
     */
    @Transactional(rollbackFor = Throwable.class)
    public void save(NoticeEntity noticeEntity, List<NoticeVisibleRangeForm> visibleRangeFormList) {
        this.getEntityMapper().insert(noticeEntity);
        Long noticeId = noticeEntity.getNoticeId();
        // 保存可见范围
        if (CollectionUtils.isNotEmpty(visibleRangeFormList)) {
            this.getEntityMapper().insertVisibleRange(noticeId, visibleRangeFormList);
        }
        dataTracerProvider.insert(noticeId, DataTracerTypeEnum.OA_NOTICE);
    }

    /**
     * 更新
     */
    @Transactional(rollbackFor = Throwable.class)
    public void update(NoticeEntity old, NoticeEntity noticeEntity, List<NoticeVisibleRangeForm> visibleRangeList) {
        this.getEntityMapper().updateById(noticeEntity);
        Long noticeId = noticeEntity.getNoticeId();
        // 保存可见范围
        if (CollectionUtils.isNotEmpty(visibleRangeList)) {
            this.getEntityMapper().deleteVisibleRange(noticeId);
            this.getEntityMapper().insertVisibleRange(noticeId, visibleRangeList);
        }
        dataTracerProvider.update(noticeId, DataTracerTypeEnum.OA_NOTICE, old, noticeEntity);
    }
}
